package http;

import http.handler.HttpServerHandler;
import http.proxy.DispatcherInterceptor;
import http.util.ApplicationContextUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import net.sf.cglib.proxy.Enhancer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public  class AbstractNettyServer {


    private int port = 8888;


    public AbstractNettyServer(String ioc) {
        ApplicationContext context=new ClassPathXmlApplicationContext(ioc,"classpath:spring-framework.xml");
        ApplicationContextUtil.setContext(context);
    }

    public void start(){
        run();
    }

    protected void run(){
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {

            ServerBootstrap serverBootstrap = new ServerBootstrap();
            // 指定socket的一些属性
            serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);
            serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)// 指定是一个NIO连接通道
                    .handler(new LoggingHandler(LogLevel.INFO)).childHandler(getChannelInitializer());

            // 绑定对应的端口号,并启动开始监听端口上的连接
            Channel ch = serverBootstrap.bind(port).sync().channel();

            System.out.printf("offer协议启动地址：127.0.0.1:%d/\n", port);
            // 等待关闭,同步端口
            ch.closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    protected  ChannelInitializer getChannelInitializer(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(HttpServerHandler.class);
        DispatcherInterceptor interceptor = ApplicationContextUtil.getBean(DispatcherInterceptor.class);
        enhancer.setCallback(interceptor);

        HttpServerHandler handler = (HttpServerHandler)enhancer.create();
        return new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast("http-decoder", new HttpRequestDecoder());
                pipeline.addLast("http-aggregator",
                        new HttpObjectAggregator(65536));
                pipeline.addLast("http-encoder", new HttpResponseEncoder());
                pipeline.addLast("http-chunked", new ChunkedWriteHandler());
                pipeline.addLast("http-handler",handler);
            }
        };
    }



    public void setPort(int port) {
        this.port = port;
    }
}
